package com.ray.depot.service.impl;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.ray.api.service.ActivitiApiService;
import com.ray.common.util.RedisNoUtil;
import com.ray.depot.enums.InOutType;
import com.ray.depot.enums.StockHoldStatus;
import com.ray.depot.service.InOutRecordService;
import com.ray.depot.service.StockHoldRecordService;
import com.ray.depot.service.StockHoldSerializeService;
import com.ray.depot.service.StockHoldService;
import com.ray.depot.table.entity.InOut;
import com.ray.depot.table.entity.InOutSerialize;
import com.ray.depot.table.entity.StockHold;
import com.ray.depot.table.entity.StockHoldRecord;
import com.ray.depot.table.entity.StockHoldRecordExample;
import com.ray.depot.table.entity.StockHoldRecordExample.Criteria;
import com.ray.depot.table.entity.StockHoldSerialize;
import com.ray.depot.table.mapper.StockHoldRecordMapper;
import com.ray.depot.table.vo.HoldVo;
import com.ray.depot.table.vo.RecordVo;
import com.xiaoleilu.hutool.util.StrUtil;
import com.zjhc.flyhong.common.function.enums.DeleteEnum;
import com.zjhc.flyhong.common.function.exception.BussinessException;
import com.zjhc.flyhong.common.function.operator.LoginUser;
import com.zjhc.flyhong.common.function.operator.PageDto;
import com.zjhc.flyhong.common.function.validate.EntityValidate;
import com.zjhc.flyhong.common.function.validate.rule.FieldRule;
import com.zjhc.flyhong.common.function.validate.rule.RuleEnum;
import com.zjhc.flyhong.common.util.UUIDUtil;
import com.zjhc.flyhong.common.web.ErrorMsg;
import com.zjhc.flyhong.common.web.Result;
import com.zjhc.flyhong.common.web.SuccessMsg;
import com.zjhc.flyhong.common.web.base.BaseService;
import com.zjhc.flyhong.redis.DefaultRedisService;

@Service
public class StockHoldRecordServiceImpl extends BaseService implements StockHoldRecordService {
	/** 日志对象 **/
	private static Logger logger = Logger.getLogger(StockHoldRecordServiceImpl.class);

	@Autowired
	private StockHoldRecordMapper stockHoldRecordMapper;
	@Autowired
	private StockHoldSerializeService stockHoldSerializeService;
	@Autowired
	private StockHoldService stockHoldService;
	@Autowired
	private DefaultRedisService defaultRedisService;
	@Autowired
	private ActivitiApiService activitiApiService;
	@Autowired
	private InOutRecordService inOutRecordService;

	
	@Transactional
	public Result<Object> addStockHoldRecord(StockHoldRecord params, LoginUser user) {
		Result<Object> result = null;
		result = new Result<Object>(0, SuccessMsg.OP_SUCCESS);
		params.setTenantId(user.getTenantId());
		params.setId(UUIDUtil.getUUID());
		params.setIsDelete(DeleteEnum.USE.getValue());
		this.setUserForAdd(params, user);
		int count = stockHoldRecordMapper.insertSelective(params);
		if (count != 1) {
			logger.error("StockHoldRecordServiceImpl=>addStockHoldRecord is error");
			throw new BussinessException(-1, ErrorMsg.INSERT_ERROR);
		}
		return result;
	}

	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public StockHoldRecord queryStockHoldRecord(String id, LoginUser user) {
		return stockHoldRecordMapper.selectByPrimaryKey(id);
	}

	@Transactional
	public Result<Object> updateStockHoldRecord(StockHoldRecord params, LoginUser user) {
		Result<Object> result = null;
		result = new Result<Object>(0, SuccessMsg.OP_SUCCESS);
		this.setUserForUpdate(params, user);
		int count = stockHoldRecordMapper.updateByPrimaryKeySelective(params);
		if (count != 1) {
			logger.error("StockHoldRecordServiceImpl=>editStockHoldRecord is error");
			throw new BussinessException(-1, ErrorMsg.INSERT_ERROR);
		}
		return result;
	}

	@Transactional
	public Result<Object> deleteStockHoldRecord(String id, LoginUser user) {
		Result<Object> result = null;
		result = new Result<Object>(0, SuccessMsg.OP_SUCCESS);
		StockHoldRecord params = new StockHoldRecord();
		params.setId(id);
		params.setIsDelete(DeleteEnum.DELETE.getValue());
		this.setUserForUpdate(params, user);
		int count = stockHoldRecordMapper.updateByPrimaryKeySelective(params);
		if (count != 1) {
			logger.error("StockHoldRecordServiceImpl=>deleteStockHoldRecord is error");
			throw new BussinessException(-1, ErrorMsg.INSERT_ERROR);
		}
		return result;
	}

	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public PageDto<StockHoldRecord> queryStockHoldRecord(StockHoldRecord params, PageDto<StockHoldRecord> page, LoginUser user) {
		StockHoldRecordExample example = new StockHoldRecordExample();
		Criteria criteria = example.createCriteria();
		// 超级管理员能查看全部
		if (!user.isSuperManager()) {
			criteria.andTenantIdEqualTo(user.getTenantId());
		} else if (user.isManager()) {
			criteria.andCreateByOrgEqualTo(user.getDeptCode());
		} else {
			criteria.andCreateByUserEqualTo(user.getUserId());
		}

		
		criteria.andIsDeleteEqualTo(DeleteEnum.USE.getValue());
		this.setExamplePage(example, page);
		page.setTotal(stockHoldRecordMapper.countByExample(example));
		page.setRecords(stockHoldRecordMapper.selectByExample(example));
		return page;
	}

	@Override
	@Transactional
	public Result<Object> saveHoldRecord(HoldVo record, Boolean isDaft, LoginUser user) {
		record.setHoldStatus(StockHoldStatus.draft.getType());
		// 草稿状态下不需要校验
		if (!isDaft) {
			// 对象验证
			FieldRule fieldRule = new FieldRule();
			fieldRule.addRule(RuleEnum.IS_NOT_NULL, String.class, "warchouseId", "仓库");
			fieldRule.addRule(RuleEnum.IS_NOT_NULL, String.class, "sourceId", "客户");
			Result<Object> result = EntityValidate.validate(record, fieldRule);
			if (!result.codeSuccess()) {
				return result;
			}

			// 校验是否为空
			if (record.getInOuts().isEmpty() && record.getInOutSerializes().isEmpty()) {
				return new Result<>(-1, "没有入库的物料或资产");
			}
			
			// 物料校验
			if (!record.getInOuts().isEmpty()) {
				for (StockHold StockHold : record.getInOuts()) {
					 fieldRule = new FieldRule();
					 fieldRule.addRule(RuleEnum.IS_NOT_NULL, Integer.class, "quantity", "数量");
					 result = EntityValidate.validate(StockHold, fieldRule);
					 if (!result.codeSuccess()) {
						return result;
					}
				}
			}
			//资产校验
			if (!record.getInOutSerializes().isEmpty()) {
				for (StockHoldSerialize StockHoldSerialize : record.getInOutSerializes()) {
					 fieldRule = new FieldRule();
					 fieldRule.addRule(RuleEnum.IS_NOT_NULL, String.class, "serializaNo", "资产号");
					 result = EntityValidate.validate(StockHoldSerialize, fieldRule);
					 if (!result.codeSuccess()) {
						return result;
					}
				}
			}
			
			record.setHoldStatus(StockHoldStatus.ToSubmit.getType());
		}

		String stockHoldNo = RedisNoUtil.createNo("YZ", defaultRedisService);
		record.setRecordNo(stockHoldNo);
		// 插入头
		this.addStockHoldRecord(record, user);
		// 插入物料
		if (!record.getInOuts().isEmpty()) {
			for (StockHold stockHold : record.getInOuts()) {
				stockHold.setRecordNo(stockHoldNo);
				stockHold.setWarchouseId(record.getWarchouseId());
				stockHoldService.addStockHold(stockHold, user);
			}
		}
		// 插入资产
		if (!record.getInOutSerializes().isEmpty()) {
			for (StockHoldSerialize stockHoldSerialize : record.getInOutSerializes()) {
				stockHoldSerialize.setRecordNo(stockHoldNo);
				stockHoldSerialize.setWarchouseId(record.getWarchouseId());
				stockHoldSerializeService.addStockHoldSerialize(stockHoldSerialize, user);
			}
		}
		return new Result<>(0, SuccessMsg.OP_SUCCESS);
	}

	@Override
	@Transactional
	public Result<Object> editHoldRecord(HoldVo record, LoginUser user) {
		 StockHoldRecord StockHoldRecord = this.queryStockHoldRecord(record.getId(), user);
		 //判断自有在草稿 审核不同意 带提交的时候才能修改
		 if(!StockHoldStatus.canEdit(StockHoldRecord.getHoldStatus())){
			 return new Result<>(-1, "该状态不能编辑");
		 }
		// 草稿状态下不需要校验
		// 对象验证
		FieldRule fieldRule = new FieldRule();
		fieldRule.addRule(RuleEnum.IS_NOT_NULL, String.class, "warchouseId", "仓库");
		fieldRule.addRule(RuleEnum.IS_NOT_NULL, String.class, "sourceId", "客户");
		fieldRule.addRule(RuleEnum.IS_NOT_NULL, String.class, "recordNo", "预占单号");
		Result<Object> result = EntityValidate.validate(record, fieldRule);
		if (!result.codeSuccess()) {
			return result;
		}
		// 校验是否为空
		if (record.getInOuts().isEmpty() && record.getInOutSerializes().isEmpty()) {
			return new Result<>(-1, "没有入库的物料或资产");
		}

		String stockHoldNo = record.getRecordNo();
		//审批驳回状态 不用修改
		if(!StrUtil.equals(StockHoldRecord.getHoldStatus(), StockHoldStatus.ApplyFail.getType())){
			record.setHoldStatus(StockHoldStatus.ToSubmit.getType());
		}
		// 插入头
		this.updateStockHoldRecord(record, user);
		// 插入物料
		// 先删除物料
		stockHoldService.deleteStockHoldByNo(stockHoldNo, user);
		if (!record.getInOuts().isEmpty()) {
			for (StockHold stockHold : record.getInOuts()) {
				stockHold.setRecordNo(stockHoldNo);
				stockHold.setWarchouseId(record.getWarchouseId());
				stockHoldService.addStockHold(stockHold, user);
			}
		}
		// 插入资产
		// 先删除资产
		stockHoldSerializeService.deleteStockHoldSerializeByNo(stockHoldNo, user);
		if (!record.getInOutSerializes().isEmpty()) {
			for (StockHoldSerialize stockHoldSerialize : record.getInOutSerializes()) {
				stockHoldSerialize.setRecordNo(stockHoldNo);
				stockHoldSerialize.setWarchouseId(record.getWarchouseId());
				stockHoldSerializeService.addStockHoldSerialize(stockHoldSerialize, user);
			}
		}

		return new Result<>(0, SuccessMsg.OP_SUCCESS);
	}

	@Override
	@Transactional
	public Result<Object> deleteHoldRecord(String id, LoginUser user) {
		StockHoldRecord StockHoldRecord = this.queryStockHoldRecord(id, user);
		if(!StockHoldStatus.canDelete(StockHoldRecord.getHoldStatus())){
			 return new Result<>(-1, "该状态不能删除");
		 }
		String StockHoldNo = StockHoldRecord.getRecordNo();
		// 删除头
		this.deleteStockHoldRecord(id, user);
		// 先删除物料
		stockHoldService.deleteStockHoldByNo(StockHoldNo, user);
		// 先删除资产
		stockHoldSerializeService.deleteStockHoldSerializeByNo(StockHoldNo, user);
	   return new Result<>(0, SuccessMsg.OP_SUCCESS);
	}

	@Override
	@Transactional
	public Result<Object> applyRecord(String stockHoldNo,String userids, String deployId, String defId, String actKey, LoginUser user) {
		StockHoldRecord StockHoldRecord = this.queryStockHoldRecordByStockHoldNo(stockHoldNo, user);
		if(!StockHoldStatus.canSubmitApply(StockHoldRecord.getHoldStatus())){
			 return new Result<>(-1, "该状态不能审核");
		 }
		//更新订单状态
		try {
			activitiApiService.startFlow(stockHoldNo, actKey, userids, deployId, defId, user);
		} catch (Exception e) {
			 throw new  BussinessException(-1,"流程启动异常");
		}
		return new Result<>(0, SuccessMsg.OP_SUCCESS);
	}
	
	public StockHoldRecord queryStockHoldRecordByStockHoldNo(String stockHoldNo, LoginUser user) {
		StockHoldRecordExample example = new StockHoldRecordExample();
		example.createCriteria().andRecordNoEqualTo(stockHoldNo)
		.andIsDeleteEqualTo(DeleteEnum.USE.getValue());
		List<StockHoldRecord> lists =  stockHoldRecordMapper.selectByExample(example);
		if(lists == null || lists.isEmpty()){
			throw new BussinessException(-1, "不存在该记录");
		}
		if(lists.size() >1){
			throw new BussinessException(-1, "查询到多条该记录");
		}
		return lists.get(0);
	}

	@Override
	@Transactional
	public void applyFail(String StockHoldNo) {
		//更新订单状态
		updateStatusByStockHoldNo(StockHoldNo,StockHoldStatus.ApplyFail.getType(),null);
	}
	
	@Override
	@Transactional
	public void applySuccess(String StockHoldNo) {
		//更新订单状态
		updateStatusByStockHoldNo(StockHoldNo,StockHoldStatus.ToHold.getType(),null);
	}
	
	@Override
	@Transactional
	public void applyIng(String StockHoldNo) {
		//更新订单状态
		updateStatusByStockHoldNo(StockHoldNo,StockHoldStatus.ToApply.getType(),null);
	}
	
	@Override
	@Transactional
	public void applyCancel(String StockHoldNo) {
		//更新订单状态
		updateStatusByStockHoldNo(StockHoldNo,StockHoldStatus.ApplyCancel.getType(),null);
	}
 
	

	   /**********************************/
		@Transactional
		private void updateStatusByStockHoldNo(String StockHoldNo, String status, LoginUser user) {
			StockHoldRecordExample example = new StockHoldRecordExample();
			example.createCriteria().andRecordNoEqualTo(StockHoldNo);
			StockHoldRecord entity = new StockHoldRecord();
			entity.setHoldStatus(status);
			//this.setUserForUpdate(entity, user);
			stockHoldRecordMapper.updateByExampleSelective(entity, example);
		}
		/**
		 * 更新zhiangt
		 * @param stockHoldNo
		 * @param entity
		 * @param user
		 */
		@Transactional
		private void updateByStockHoldNo(String stockHoldNo, StockHoldRecord entity , LoginUser user) {
			StockHoldRecordExample example = new StockHoldRecordExample();
			example.createCriteria().andRecordNoEqualTo(stockHoldNo);
			this.setUserForUpdate(entity, user);
			stockHoldRecordMapper.updateByExampleSelective(entity, example);
		}
        /**
         * 预占
         */
		@Override
		@Transactional
		public Result<Object> holdIn(String id, LoginUser user) {
			StockHoldRecord stockHoldRecord = this.queryStockHoldRecord(id, user);
			if(!StockHoldStatus.canHold(stockHoldRecord.getHoldStatus())){
				 return new Result<>(-1, "该状态不能预占");
			 }
			stockHoldRecord.setHoldStatus(StockHoldStatus.HoldSuccess.getType());
			stockHoldRecord.setHoldUser(user.getUserId());
			
			List<StockHold> stockHolds = stockHoldService.queryStockHoldsByStockHoldNo(stockHoldRecord.getRecordNo(), user);
			List<StockHoldSerialize> stockHoldSerializes = stockHoldSerializeService.queryStockHoldSerializesByStockHoldNo(stockHoldRecord.getRecordNo(), user);
			RecordVo record = new RecordVo(); 
			record.setSourceId(stockHoldRecord.getSourceId());
			record.setWarchouseId(stockHoldRecord.getWarchouseId());
			record.setInOutType(InOutType.HoldOut.getType());
			 
			List<InOut> inOuts = new ArrayList<InOut>();
			List<InOutSerialize> inOutSerializes = new ArrayList<InOutSerialize>();
			InOut inOut = null;
			for(StockHold stockHold : stockHolds){
				inOut = new InOut();
				try {
					PropertyUtils.copyProperties(inOut,stockHold);
				} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
					throw new BussinessException(-1, "数据转换异常.");
				}
				inOuts.add(inOut);
			}
			record.setInOuts(inOuts);
			//资产
			InOutSerialize inOutSerialize = null;
			for(StockHoldSerialize stockHoldSerialize : stockHoldSerializes){
				inOutSerialize = new InOutSerialize();
				try {
					PropertyUtils.copyProperties(inOutSerialize,stockHoldSerialize);
				} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
					throw new BussinessException(-1, "数据转换异常.");
				}
				inOutSerializes.add(inOutSerialize);
			}
			record.setInOutSerializes(inOutSerializes);
			//生成待出库单
			//RecordVo recordVo = inOutRecordService.saveOutRecord(record,InOutStatus.ToInOut.getType(), user);
			RecordVo recordVo = inOutRecordService.saveOutRecordAndDoOut(record, user);
			stockHoldRecord.setOutNo(recordVo.getInOutNo());//出库单号
			updateByStockHoldNo(stockHoldRecord.getRecordNo(),stockHoldRecord,user);
			
			return new Result<>(0, SuccessMsg.OP_SUCCESS);
		}
	
		@Override
		@Transactional
		public Result<Object> holdUse(String id, LoginUser user) {
			StockHoldRecord stockHoldRecord = this.queryStockHoldRecord(id, user);
			if(!StockHoldStatus.canHoldUse(stockHoldRecord.getHoldStatus())){
				 return new Result<>(-1, "该状态不能使用预占");
			 }
			updateStatusByStockHoldNo(stockHoldRecord.getRecordNo(),StockHoldStatus.HoldUse.getType(),null);
			return new Result<>(0, SuccessMsg.OP_SUCCESS);
		}
	
		@Override
		@Transactional
		public Result<Object> holdCancel(String id, LoginUser user) {
			StockHoldRecord stockHoldRecord = this.queryStockHoldRecord(id, user);
			if(!StockHoldStatus.canHoldCacnel(stockHoldRecord.getHoldStatus())){
				 return new Result<>(-1, "该状态不能预占取消");
			 }
			stockHoldRecord.setHoldStatus(StockHoldStatus.HoldCancel.getType());
			stockHoldRecord.setResetUser(user.getUserId());
			List<StockHold> stockHolds = stockHoldService.queryStockHoldsByStockHoldNo(stockHoldRecord.getRecordNo(), user);
			List<StockHoldSerialize> stockHoldSerializes = stockHoldSerializeService.queryStockHoldSerializesByStockHoldNo(stockHoldRecord.getRecordNo(), user);
			RecordVo record = new RecordVo(); 
			record.setSourceId(stockHoldRecord.getSourceId());
			record.setWarchouseId(stockHoldRecord.getWarchouseId());
			record.setInOutType(InOutType.HoldIn.getType());
			 
			List<InOut> inOuts = new ArrayList<InOut>();
			List<InOutSerialize> inOutSerializes = new ArrayList<InOutSerialize>();
			InOut inOut = null;
			for(StockHold stockHold : stockHolds){
				inOut = new InOut();
				try {
					PropertyUtils.copyProperties(inOut,stockHold);
				} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
					throw new BussinessException(-1, "数据转换异常.");
				}
				inOuts.add(inOut);
			}
			record.setInOuts(inOuts);
			//资产
			InOutSerialize inOutSerialize = null;
			for(StockHoldSerialize stockHoldSerialize : stockHoldSerializes){
				inOutSerialize = new InOutSerialize();
				try {
					PropertyUtils.copyProperties(inOutSerialize,stockHoldSerialize);
				} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
					throw new BussinessException(-1, "数据转换异常.");
				}
				inOutSerializes.add(inOutSerialize);
			}
			record.setInOutSerializes(inOutSerializes);
			//RecordVo recordVo = inOutRecordService.saveInRecord(record,InOutStatus.ToInOut.getType(), user);
			RecordVo recordVo = inOutRecordService.saveInRecordAndDoIn(record, user);
			stockHoldRecord.setInNo(recordVo.getInOutNo());//入库
			updateByStockHoldNo(stockHoldRecord.getRecordNo(),stockHoldRecord,user);
			//入库
			return new Result<>(0, SuccessMsg.OP_SUCCESS);
		}

		

}
